﻿using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using FF14TreasureDiggingTool.DataAccess.ApplicationDbContext;
using FF14TreasureDiggingTool.DataAccess.Enums;
using FF14TreasureDiggingTool.DataAccess.Models;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
using Wpf.Ui.Common.Interfaces;
using Wpf.Ui.Controls.Interfaces;
using Wpf.Ui.Mvvm.Contracts;

namespace FF14TreasureDiggingTool.ViewModels;

public partial class ForecastViewModel : ObservableObject, INavigationAware
{
    private readonly ApplicationContext _dbContext;
    private readonly IDialogControl _dialogControl;
    private readonly ISnackbarControl _snackbarControl;
    private ObservableCollection<SpecialEvent> _addedEvents;

    [ObservableProperty]
    private CustomRule _customRule;

    [ObservableProperty]
    private int? _deepestLayer;

    private ObservableCollection<SpecialEvent> _enemyEvents;

    [ObservableProperty]
    private int _eventLayer;

    [ObservableProperty]
    private List<FloorInfo> _floorInfos;

    [ObservableProperty]
    private bool _isAutoClearEvent;

    private bool _isInitialized;

    [ObservableProperty]
    private bool _isObtainTreasure;

    [ObservableProperty]
    private List<int> _layers;

    private Dictionary<int, string> _layersRecords;

    [ObservableProperty]
    private List<CustomRule> _rules;

    [ObservableProperty]
    private string? _selectedServer;

    [ObservableProperty]
    private List<string> _serversList;

    private ObservableCollection<SpecialEvent> _strongDesireEvents;

    [ObservableProperty]
    private List<SpecialEvent> _totalEvents;

    [ObservableProperty]
    private int _totalFactor;

    private ObservableCollection<SpecialEvent> _treasureEvents;

    public ForecastViewModel(
        IDialogService dialogService,
        ApplicationContext dbContext,
        ISnackbarService snackbarService
    )
    {
        _dialogControl = dialogService.GetDialogControl();
        _dbContext = dbContext;
        System.Diagnostics.Debug.WriteLine($"Forecast里的上下文Id{_dbContext.ContextId}");

        _snackbarControl = snackbarService.GetSnackbarControl();
    }

    public ObservableCollection<SpecialEvent> AddedEvents
    {
        get => _addedEvents;
        set => SetProperty(ref _addedEvents, value);
    }
    public ObservableCollection<SpecialEvent> EnemyEvents
    {
        get => _enemyEvents;
        set => SetProperty(ref _enemyEvents, value);
    }
    public ObservableCollection<SpecialEvent> StrongDesireEvents
    {
        get => _strongDesireEvents;
        set => SetProperty(ref _strongDesireEvents, value);
    }

    public ObservableCollection<SpecialEvent> TreasureEvents
    {
        get => _treasureEvents;
        set => SetProperty(ref _treasureEvents, value);
    }

    [RelayCommand]
    public void AddEvent(SpecialEvent specialEvent)
    {
        AddedEvents.Add(specialEvent);
        TotalFactor = AddedEvents.Sum(e => e.Factor);
    }

    [RelayCommand]
    public async void AddRecord()
    {
        if (DeepestLayer is null)
        {
            _snackbarControl.Show("未选择进洞最深层", "");
            return;
        }

        if (SelectedServer is null)
        {
            _snackbarControl.Show("未选择进洞服务器", "");
            return;
        }

        var dungeonsRecord = new DungeonsRecord()
        {
            RuleName = CustomRule.RuleName,
            DateRecord = DateTime.Now,
            IsObtainTreasure = IsObtainTreasure ? "是" : "否",
            CurrentServer = SelectedServer,
            DeepestLayer = (int)DeepestLayer,
            Layer1Record = _layersRecords[1],
            Layer2Record = _layersRecords[2],
            Layer3Record = _layersRecords[3],
            Layer4Record = _layersRecords[4],
            Layer5Record = _layersRecords[5],
            Layer6Record = _layersRecords[6]
        };

        var dialogString = $"地表出货：{dungeonsRecord.IsObtainTreasure}{Environment.NewLine}";
        dialogString += $"服务器：{dungeonsRecord.CurrentServer}{Environment.NewLine}";
        dialogString +=
            $"第一层：{Environment.NewLine}{_layersRecords[1]}{Environment.NewLine}{Environment.NewLine}";
        dialogString +=
            $"第二层：{Environment.NewLine}{_layersRecords[2]}{Environment.NewLine}{Environment.NewLine}";
        dialogString +=
            $"第三层：{Environment.NewLine}{_layersRecords[3]}{Environment.NewLine}{Environment.NewLine}";
        dialogString +=
            $"第四层：{Environment.NewLine}{_layersRecords[4]}{Environment.NewLine}{Environment.NewLine}";
        dialogString +=
            $"第五层：{Environment.NewLine}{_layersRecords[5]}{Environment.NewLine}{Environment.NewLine}";
        dialogString += $"第六层：{Environment.NewLine}{_layersRecords[6]}";

        _dialogControl.DialogHeight = 800;
        _dialogControl.ButtonLeftName = "取消";
        _dialogControl.ButtonRightName = "确认";

        var button = await _dialogControl.ShowAndWaitAsync("确认保存？", dialogString, true);

        if (button == IDialogControl.ButtonPressed.Left)
        {
            return;
        }

        _dbContext.DungeonsRecords.Add(dungeonsRecord);
        _dbContext.SaveChanges();
        _snackbarControl.Show("保存成功", "");

        for (int i = 1; i <= 6; i++)
        {
            _layersRecords[i] = string.Empty;
        }

        IsObtainTreasure = false;
    }

    [RelayCommand]
    public void ClearEvent()
    {
        AddedEvents.Clear();
        TotalFactor = 0;
    }

    [RelayCommand]
    public void ClearLayerRecord()
    {
        if (DeepestLayer is null)
        {
            _snackbarControl.Show("未指定楼层", "");
            return;
        }

        _layersRecords[(int)DeepestLayer] = string.Empty;
        _snackbarControl.Show($"已清空第{DeepestLayer}层记录", "");
    }

    [RelayCommand]
    public async void ForecastDoor(FloorInfo floorInfo)
    {
        _dialogControl.DialogHeight = 300;

        if (!floorInfo.RouteOptions.Exists(r => r.IsSelected))
        {
            _dialogControl.ButtonLeftName = "取消";
            _dialogControl.ButtonRightName = "确认";
            _dialogControl.Show("预测结果", "未选择该层出现的怪物，请选择后再点击预测开门按钮。");
            return;
        }

        var route = floorInfo.RouteOptions.First(r => r.IsSelected);
        int actualFactor = TotalFactor + Convert.ToInt16(floorInfo.IsClockInverse);
        bool isFactorEven = actualFactor % 2 == 0;
        DoorPosition openDoor =
            route.DoorPosition == DoorPosition.左
                ? (isFactorEven ? DoorPosition.左 : DoorPosition.右)
                : (isFactorEven ? DoorPosition.右 : DoorPosition.左);

        string isClockInverse = floorInfo.IsClockInverse ? "是" : "否";
        string eventString = "";
        foreach (var e in AddedEvents)
        {
            eventString += e.EventName + $"[{e.Factor}]" + "，";
        }

        string recordString = $"时钟反转：{isClockInverse}{Environment.NewLine}";
        recordString += $"怪物：{route.EnemyType}[{route.DoorPosition}]{Environment.NewLine}";
        recordString += $"事件：{eventString.TrimEnd(new char[] { '，' })}{Environment.NewLine}";
        recordString += $"总系数：{actualFactor}{Environment.NewLine}";
        recordString += $"预测开门：{openDoor}{Environment.NewLine}";

        _dialogControl.DialogHeight = 300;
        _dialogControl.ButtonLeftName = "实际选门：左";
        _dialogControl.ButtonRightName = "实际选门：右";

        var button = await _dialogControl.ShowAndWaitAsync("预测结果", recordString, true);
        string buttonString = button == IDialogControl.ButtonPressed.Left ? "左" : "右";

        recordString += $"实际选门：{buttonString}";

        _layersRecords[floorInfo.FloorNum] = recordString;

        if (IsAutoClearEvent)
        {
            ClearEvent();
        }
    }

    public void OnNavigatedFrom() { }

    public void OnNavigatedTo()
    {
        if (_isInitialized)
        {
            var selectedRule = new CustomRule();

            if (_dbContext.CustomRules.Where(c => c.IsCurrentRule).ToList().Count > 0)
            {
                selectedRule = _dbContext.CustomRules.First(c => c.IsCurrentRule == true);
            }
            else
            {
                selectedRule = _dbContext.CustomRules.First();
            }

            if (selectedRule.Id != CustomRule.Id)
            {
                LoadRule();
            }
        }

        if (!_isInitialized)
        {
            InitializeViewModel();
            LoadRule();
        }
    }

    [RelayCommand]
    public void ReloadRule()
    {
        LoadRule();
    }

    [RelayCommand]
    public void RemoveEvent(SpecialEvent specialEvent)
    {
        AddedEvents.Remove(specialEvent);
        TotalFactor = AddedEvents.Sum(e => e.Factor);
    }

    private static void DialogControlButtonRightClick(object sender, RoutedEventArgs e)
    {
        var dialogControl = (IDialogControl)sender;
        dialogControl.Hide();
    }

    private void InitializeViewModel()
    {
        _layersRecords = new Dictionary<int, string>()
        {
            { 1, string.Empty },
            { 2, string.Empty },
            { 3, string.Empty },
            { 4, string.Empty },
            { 5, string.Empty },
            { 6, string.Empty }
        };

        TotalFactor = 0;
        AddedEvents = new ObservableCollection<SpecialEvent>();

        Layers = new List<int>() { 1, 2, 3, 4, 5, 6 };

        ServersList = new List<string>()
        {
            "拉诺西亚",
            "幻影群岛",
            "神意之地",
            "萌芽池",
            "红玉海",
            "宇宙和音",
            "沃仙曦染",
            "晨曦王座",
            "潮风亭",
            "神拳痕",
            "白银乡",
            "白金幻象",
            "旅人栈桥",
            "拂晓之间",
            "龙巢神殿",
            "梦羽宝境",
            "紫水栈桥",
            "延夏",
            "静语庄园",
            "摩杜纳",
            "海猫茶屋",
            "柔风海湾",
            "琥珀原",
            "水晶塔",
            "银泪湖",
            "太阳海岸",
            "伊修加德",
            "红茶川",
        };

        _dialogControl.ButtonLeftClick += DialogControlButtonRightClick;
        _dialogControl.ButtonRightClick += DialogControlButtonRightClick;
        IsAutoClearEvent = false;
        _isInitialized = true;
    }

    private void LoadRule()
    {
        CustomRule = _dbContext.CustomRules
            .Include(r => r.FloorInfos)
            .ThenInclude(f => f.RouteOptions)
            .Include(c => c.TotalEvents)
            .AsNoTracking()
            .FirstOrDefault(c => c.IsCurrentRule == true);

        if (CustomRule is null)
        {
            CustomRule = _dbContext.CustomRules
                .Include(r => r.FloorInfos)
                .ThenInclude(f => f.RouteOptions)
                .Include(c => c.TotalEvents)
                .AsNoTracking()
                .First();
        }

        FloorInfos = CustomRule.FloorInfos.OrderBy(f => f.FloorNum).ToList();
        TotalEvents = CustomRule.TotalEvents;

        EnemyEvents = new ObservableCollection<SpecialEvent>(
            TotalEvents
                .Where(e => e.EventType == EventType.EnemyEvent)
                .OrderBy(e => e.Sort)
                .ToList()
        );

        TreasureEvents = new ObservableCollection<SpecialEvent>(
            TotalEvents
                .Where(e => e.EventType == EventType.TreasureEvent)
                .OrderBy(e => e.Sort)
                .ToList()
        );

        StrongDesireEvents = new ObservableCollection<SpecialEvent>(
            TotalEvents
                .Where(e => e.EventType == EventType.StrongDesireEvent)
                .OrderBy(e => e.Sort)
                .ToList()
        );
        _snackbarControl.Show($"当前规则：{CustomRule.RuleName}");
    }
}
